﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Domain.NetworkRemoteDevice;
using Domain.NetworkService;
using Domain.Entities;
using System.Threading;
using Domain.NetworkService.Behaviors.Interfaces;
using System.IO;
using System.Diagnostics;
namespace Domain.NetworkRemoteDevice
{
    public static class RemoteDeviceManager
    {
        private static string pathToSave = System.Configuration.ConfigurationManager.AppSettings["pathToSave"];
        public static string PathToSave
        {
            get { return RemoteDeviceManager.pathToSave; }
        }
        static List<RemoteDevice> remoteDevices = new List<RemoteDevice>();
        static List<NetworkServiceState> nss;
        public static OperationStatus SaveState(string fileName = "default.dat")
        {
            nss = new List<NetworkServiceState>();
            Thread.Sleep(1000);
            foreach (var rd in remoteDevices)
            {
                foreach (var t in rd.Tests)
                {
                    nss.Add(new NetworkServiceState()
                            {
                                isActive = t.isActive(),
                                networkServiceTestID = t.ID
                            });
                }
            }
            Serializer serializer = new Serializer();
            try
            {
                serializer
                    .saveNetworkServiceStates
                    (nss, pathToSave + fileName);
            }
            catch (Exception e)
            {
                DBWorker db = new DBWorker();
                db.WriteLog(e.Message, MessageType.Error);
                return OperationStatus.SaveStateFailed;
            }
            return OperationStatus.SaveStateCompleted;
        }
        public static OperationStatus LoadState(string fileName = "default.dat")
        {
            Serializer serializer = new Serializer();
            try
            {
                if (serializer.loadNetworkServiceStates(pathToSave+fileName))
                {
                    nss = serializer.NetworkServiceStates;
                }
                else { }
            }
            catch (Exception e)
            {
                DBWorker db = new DBWorker();
                db.WriteLog(e.Message, MessageType.Error);
                return OperationStatus.LoadStateFailed;
            }
            foreach (var item in nss)
            {
                TestsSimpleFabric tsf = new TestsSimpleFabric();
                AddRemoteDevice(item.networkServiceTestID.deviceName);
                if (tsf.MakeTest(item.networkServiceTestID.description))
                {
                    AddTestToRemoteDevice(item.networkServiceTestID.deviceName,
                                         tsf.Test);
                    if (item.isActive)
                    {
                        StartSomeTest(item.networkServiceTestID.deviceName,
                                        item.networkServiceTestID.description);
                    }
                }
                else
                { }
            }
            return OperationStatus.LoadStateSuccess;
        }
        public static OperationStatus RemoveRemoteDevice(string deviceName)
        {
            if (remoteDevices.Exists(o => o.Name.Equals(deviceName)))
            {
                RemoteDevice rd = remoteDevices.FindAll(o => o.Name.Equals(deviceName)).First();
                foreach (var item in rd.Tests)
                {
                    item.Stop();
                }
                remoteDevices.RemoveAll(o => o.Name.Equals(deviceName));
                return OperationStatus.Success;
            }
            return OperationStatus.DeviceNotFound;
        }
        public static OperationStatus AddRemoteDevice(string deviceName)
        {
            if (!remoteDevices.Exists(o => o.Name.Equals(deviceName)))
            {
                RemoteDevice rd = new RemoteDevice(deviceName);
                remoteDevices.Add(rd);
                return OperationStatus.Success;
            }
            return OperationStatus.DeviceAlreadyExists;
        }
        public static List<string> GetNamesOfRemoteDevices()
        {
            var names = new List<string>();
            foreach (var item in remoteDevices)
            {
                names.Add(item.Name);
            }
            return names;
        }
        public static List<NetworkTestResult> GetLastResultOfAllTestsOfRemoteDevice(string deviceName)
        {
            List<NetworkTestResult> listResult = new List<NetworkTestResult>();
            var tests = GetTestsNamesOfRemoteDevice(deviceName);
            DBWorker db = new DBWorker();

            foreach (var item in tests)
            {
                if (item.networkServiceTestID.description.networkTestDescription.Equals(NetworkTestDescription.ECHO))
                {
                    listResult.Add(db.getLastEchoResult(deviceName));
                }
                if (item.networkServiceTestID.description.networkTestDescription.Equals(NetworkTestDescription.NS))
                {
                    listResult.Add(db.getLastResolveResult(deviceName));
                }
                if (item.networkServiceTestID.description.networkTestDescription.Equals(NetworkTestDescription.SNMP))
                {
                    listResult.Add(db.getLastSnmpResult(deviceName, item.networkServiceTestID.description.Special));
                }
                if (item.networkServiceTestID.description.networkTestDescription.Equals(NetworkTestDescription.TCP))
                {
                    listResult.Add(db.getLastTCPResult(deviceName, item.networkServiceTestID.description.Special));
                }
            }
            return listResult;
        }
        public static bool hasDevice(string deviceName)
        {
            List<string> names = GetNamesOfRemoteDevices();
            foreach (var item in names)
            {
                if (item.Equals(deviceName))
                {
                    return true;
                }
            }
            return false;
        }
        
        public static List<NetworkServiceState> GetTestsNamesOfRemoteDevice(string deviceName)
        {
            var result = new List<NetworkServiceState>();
            foreach (var rd in remoteDevices)
            {
                if (rd.Name.Equals(deviceName))
                {
                    foreach (var item in rd.Tests)
                    {
                        result.Add(new NetworkServiceState { networkServiceTestID = item.ID, isActive = item.isActive()});
                    }
                    return result;
                }
            }
            return null;
        }
        public static OperationStatus AddTestToRemoteDevice(string deviceName, INetworkServiceTest test)
        {
            if (remoteDevices.Exists(o => o.Name.Equals(deviceName)))
            {
                RemoteDevice rd = remoteDevices.FindAll(o => o.Name.Equals(deviceName)).First();
                if (rd.AddTest(test))
                {
                    return OperationStatus.Success;
                }
                return OperationStatus.TestAlreadyExists;
            }
            return OperationStatus.DeviceNotFound;
        }
        public static OperationStatus RemoveTestFromRemoteDevice(string deviceName, IDescription description)
        {
            if (remoteDevices.Exists(o => o.Name.Equals(deviceName)))
            {
                RemoteDevice rd = remoteDevices.FindAll(o => o.Name.Equals(deviceName)).First();

                if (rd.RemoveTest(description))
                {
                    return OperationStatus.Success;
                }
                return OperationStatus.TestNotFound;
            }
            return OperationStatus.DeviceNotFound;
        }
        public static int StartAllTests()
        {
            int count = 0;
            remoteDevices
                .ForEach(rd => rd
                    .Tests.ForEach(t =>
                    {
                        t.Run();
                        count++;
                    }));
            return count;
        }
        public static int StopAllTests()
        {
            int count = 0;
            remoteDevices
                .ForEach(rd => rd
                    .Tests.ForEach(t =>
                        {
                            t.Stop();
                            count++;
                        }));
            return count;
        }
        public static OperationStatus StartAllTestsOfRemoteDevice(string deviceName)
        {
            foreach (var rd in remoteDevices)
            {
                if (rd.Name.Equals(deviceName))
                {
                    foreach (var item in rd.Tests)
                    {
                        item.Run();
                    }
                    return OperationStatus.Success;
                }
            }
            return OperationStatus.DeviceNotFound;
        }
        public static OperationStatus StopAllTestsOfRemoteDevice(string deviceName)
        {
            foreach (var rd in remoteDevices)
            {
                if (rd.Name.Equals(deviceName))
                {
                    foreach (var item in rd.Tests)
                    {
                        item.Stop();
                    }
                    return OperationStatus.Success;
                }
            }
            return OperationStatus.DeviceNotFound;
        }
        public static OperationStatus StartSomeTest(String deviceName, IDescription description)
        {
            foreach (var rd in remoteDevices)
            {
                if (rd.Name.Equals(deviceName))
                {
                    foreach (var item in rd.Tests)
                    {
                        NetworkServiceTestID id = new NetworkServiceTestID(deviceName, description);
                        if (item.ID.Equals(id))
                        {
                            item.Run();
                            return OperationStatus.Success;
                        }
                    }
                    return OperationStatus.TestNotFound;
                }
            }
            return OperationStatus.DeviceNotFound;
        }
        public static OperationStatus StopSomeTest(String deviceName, IDescription description)
        {
            foreach (var rd in remoteDevices)
            {
                if (rd.Name.Equals(deviceName))
                {
                    foreach (var item in rd.Tests)
                    {
                        NetworkServiceTestID id = new NetworkServiceTestID(deviceName, description);
                        if (item.ID.Equals(id))
                        {
                            item.Stop();
                            return OperationStatus.Success;
                        }
                    }
                    return OperationStatus.TestNotFound;
                }
            }
            return OperationStatus.DeviceNotFound;
        }
        /// <summary>
        /// TestName is ID.ToString()
        /// </summary>
        /// <param name="testName"></param>
        /// <returns></returns>
        public static IDescription GetIDescriptionByTestName(string testName)
        {
            foreach (var rd in remoteDevices)
            {
                foreach (var test in rd.Tests)
                {
                    if (test.ID.ToString().Equals(testName))
                    {
                        return test.ID.description as IDescription;
                    }
                }
            }
            return null;
        }
    }
}
